package biz.inspeed.test.queu;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;

public class Client implements Runnable {

	public static void main(String[] args) {
		final Client c = new Client();
		new Thread(c).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				c.receiveFromConsole();
			}
		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					try {
						System.out.println(DataStore.cReceiveQueue.take());
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}).start();
	}

	private BlockingQueue<Object> cSendQueue;
	private BlockingQueue<Object> cReceiveQueue;

	public Client() {
		this.cReceiveQueue = DataStore.cReceiveQueue;
		this.cSendQueue = DataStore.cSendQueue;
		try {
			init();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// ObjectInputStream objectInStream = new
		// ObjectInputStream(socket.getInputStream());
		// ObjectOutputStream objectOutStream = new
		// ObjectOutputStream(socket.getOutputStream());
		new Thread(new readThread(socket)).start();
		new Thread(new writeThread(socket)).start();
	}

	private SocketChannel socketChannel;
	private Selector selector;
	private String host = "192.168.0.240";
	private int port = 0xBeef;
	private Socket socket;

	private void init() throws IOException {
		socket = new Socket(host, port);

		// this.socketChannel = SocketChannel.open();
		// this.socketChannel.configureBlocking(false);
		// InetSocketAddress isa = new InetSocketAddress(host, port);
		// this.socketChannel.connect(isa);
		// this.selector = Selector.open();
		System.out.println("Connect to server success");
	}

	public void receiveFromConsole() {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String msg = null;
		try {
			while ((msg = br.readLine()) != null) {
				String[] strings = msg.split("\\s+");
				for(String s : strings){
					Message m = new Message(DataStore.id++, s);
					this.cSendQueue.add(m);
				}
				if (msg.equals("bye")) {
					break;
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void doRead(SelectionKey key) throws IOException,
			ClassNotFoundException {
		SocketChannel socket = (SocketChannel) key.channel();
		ObjectInputStream ois = new ObjectInputStream(socket.socket()
				.getInputStream());
		while (ois.available() > 0) {
			Object o = ois.readObject();
			this.cReceiveQueue.add(o);
		}
	}

	private void doWrite(SelectionKey key) throws IOException {
		SocketChannel socket = (SocketChannel) key.channel();
		ObjectOutputStream oos = new ObjectOutputStream(socket.socket()
				.getOutputStream());
		while (true) {
			try {
				oos.writeObject(this.cSendQueue.take());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	class readThread implements Runnable {
		private Socket socket;

		public readThread(Socket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				ObjectInputStream objectInStream = new ObjectInputStream(
						socket.getInputStream());
				while (true) {
					Object object = objectInStream.readObject();
					cReceiveQueue.add(object);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	class writeThread implements Runnable {

		private ObjectOutputStream objectOutStream;
		private Socket socket;

		public writeThread(Socket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				this.objectOutStream = new ObjectOutputStream(
						this.socket.getOutputStream());
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			while (true) {
				try {
					Object o = cSendQueue.take();
					this.objectOutStream.writeObject(o);
				} catch (IOException | InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
